package com.atguigu.guli.service.edu.service.impl;

import com.alibaba.excel.EasyExcel;
import com.atguigu.guli.service.base.exception.GuliException;
import com.atguigu.guli.service.base.result.ResultCodeEnum;
import com.atguigu.guli.service.edu.entity.Subject;
import com.atguigu.guli.service.edu.entity.excel.SubjectExceldata;
import com.atguigu.guli.service.edu.listener.SubjectDataListener;
import com.atguigu.guli.service.edu.mapper.SubjectMapper;
import com.atguigu.guli.service.edu.service.SubjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程科目 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2021-06-27
 */
@Service
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, Subject> implements SubjectService {

    @Override
    public void importSubjects(MultipartFile file) {
        //1、为excel文档创建bean 描述excel和bean的映射关系
        //2、创建监听器： 解析excel并转为对象
        //3、使用asyexcel 读取数据交给监听器使用数据
        try {
            EasyExcel.read(file.getInputStream())
                    .sheet(0)
                    .registerReadListener(new SubjectDataListener(baseMapper))
                    .head(SubjectExceldata.class)
                    .doRead();
        } catch (Exception e) {//ExcelAnalysisException
            //当前捕获异常的为编译时的异常，必须处理，但是如果真的出现了能够捕获的异常，代码正常执行
            //响应给前端的是处理成功
            e.printStackTrace();
//            throw new RuntimeException(); //将编译异常转为运行异常抛出，当捕获到异常时仍然抛出异常
            //当抛出RuntimeException，全局异常处理器可以单独处理，但是不方便给前端提示异常的原因
            //我们可以自定义一个异常，在异常对象中携带需要描述的异常信息
//            log.error(ExceptionUtils.getStackTrace(e));//真正的异常信息
            throw new GuliException(ResultCodeEnum.EXCEL_DATA_IMPORT_ERROR);
        }
    }

    @Override
    public List<Subject> getSubjectsNestedList() {
        // 逆向生成的业务和mapper的方法 只能操作单表的CRUD
//        baseMapper.  自定义sql
        //由于 多表查询用的是一张表拆分查询的，查询的结果集 也都是这张表的所有数据
        // 只要查询表的所有数据  然后使用业务代码  将数据拆分为一级二级的父子分类数据集合

        List<Subject> subjects = baseMapper.selectList(null);

        //筛选一级分类 并存到map中
        Map<String , Subject> pmap = new HashMap(); // key：一级分类自己的id   value：一级分类对象


        for (Subject subject : subjects) {
            //如果一个课程分类的父id为0 代表它是1级分类
            if("0".equals(subject.getParentId())){
                pmap.put(subject.getId()  , subject);
            }
        }
        //  二级分类.getParentId()
        //挑选二级分类的一级分类对象，将二级分类设置到它的子分类集合中
        for (Subject subject : subjects) {
            if(!"0".equals(subject.getParentId())){
                //获取当前二级分类的一级分类对象
                Subject psubject = pmap.get(subject.getParentId());
                psubject.getChildren().add(subject);
            }
        }
        return new ArrayList<Subject>(pmap.values());
    }
}
